import pymiere
from pymiere.wrappers import time_from_seconds
import sys
import atexit


# ==================== 异常处理模块 ====================
def ignore_pymiere_shutdown_errors():
    """抑制pymiere退出时的无害异常"""
    original_hook = sys.excepthook

    def custom_hook(exc_type, exc_val, exc_tb):
        error_msg = str(exc_val)
        if "PymiereBaseObject" in error_msg or "sys.meta_path" in error_msg:
            return
        original_hook(exc_type, exc_val, exc_tb)

    sys.excepthook = custom_hook


def cleanup_pymiere():
    """显式释放pymiere资源"""
    global project_cache
    # 清理缓存
    project_cache.bins.clear()
    project_cache.bin_clips.clear()
    project_cache.track_info.clear()
    project_cache.position_props.clear()

    # 关闭网络连接
    if hasattr(pymiere.core, '_connection'):
        try:
            pymiere.core._connection.close()
        except Exception as e:
            pass
        del pymiere.core._connection


# 初始化异常处理
ignore_pymiere_shutdown_errors()
atexit.register(cleanup_pymiere)


# ==================== 项目缓存模块 ====================
class ProjectCache:
    def __init__(self):
        self.bins = {}  # 素材箱名称 -> 素材箱对象
        self.bin_clips = {}  # 素材箱名称 -> {剪辑名称: 剪辑对象}
        self.track_info = []  # 轨道信息缓存
        self.position_props = {}  # 剪辑对象 -> 位置属性对象

    def build_cache(self):
        """构建项目缓存（只需调用一次）"""
        self._cache_bins_and_clips()
        self._cache_initial_tracks()

    def _cache_bins_and_clips(self):
        """缓存所有素材箱及其包含的剪辑"""
        stack = []
        root_item = pymiere.objects.app.project.rootItem

        # 遍历根素材箱（使用数字类型标识）
        for bin_item in root_item.children:
            if bin_item.type == 2:  # 2表示素材箱类型
                self._add_bin_to_cache(bin_item, stack)

        # 处理嵌套素材箱
        while stack:
            current_bin = stack.pop()
            for child in current_bin.children:
                if child.type == 2:  # 2表示素材箱类型
                    self._add_bin_to_cache(child, stack)

    def _add_bin_to_cache(self, bin_item, stack):
        """将素材箱添加到缓存"""
        self.bins[bin_item.name] = bin_item
        stack.append(bin_item)
        self.bin_clips[bin_item.name] = {}

        # 缓存素材箱中的剪辑（1表示剪辑类型）
        for child in bin_item.children:
            if child.type == 1:  # 1表示剪辑类型
                self.bin_clips[bin_item.name][child.name] = child

    def _cache_initial_tracks(self):
        """缓存初始轨道信息"""
        seq = pymiere.objects.app.project.activeSequence
        self.track_info = [
            {
                "index": i,
                "clip_count": len(track.clips),
                "clips": list(track.clips)
            }
            for i, track in enumerate(seq.videoTracks)
        ]

    def get_clip(self, bin_name, clip_name):
        """从缓存获取剪辑对象"""
        return self.bin_clips.get(bin_name, {}).get(clip_name)

    def get_position_property(self, clip):
        """获取并缓存位置属性"""
        if clip not in self.position_props:
            for comp in clip.components:
                if comp.displayName == "运动":
                    for prop in comp.properties:
                        if prop.displayName == "位置":
                            self.position_props[clip] = prop
                            break
                    break
        return self.position_props.get(clip)


# ==================== 全局配置 ====================
TRACK_CONFIG = {
    "positions": {
        0: (100, 100),  # 轨道1位置
        1: (200, 200),  # 轨道2位置
        2: (1720, 930),  # 建造列表
        3: (1816, 650),  # 自己农民死亡
        4: (100, 650),  # 敌方农民死亡
        5: (1812, 200),  # 科技1
        6: (1812, 300),  # 科技2
        7: (1812, 400),  # 科技3
        8: (1692, 905),  # 战损栏
        9: (1000, 1000),  # 备用位置
    },
    "delays": {
        0: 0,  # 无延迟
        1: 1,  # 1秒延迟
        2: 60,  # 1分钟延迟
        3: 63,  # 其他轨道统一延迟
        4: 63,
        5: 63,
        6: 63,
        7: 63,
        8: 63,
        9: 63,
    }
}


# ==================== 工具函数 ====================
def time_to_seconds(time_str):
    """将 MM:SS 格式时间转换为秒"""
    try:
        return sum(x * int(t) for x, t in zip([60, 1], time_str.split(":")))
    except ValueError:
        raise ValueError(f"无效时间格式: {time_str}，请使用 MM:SS 格式")


# ==================== 主操作函数 ====================
def insert_and_position_clip(bin_name, clip_name, track_idx, mmss_time):
    """
    插入剪辑到指定轨道并设置位置
    参数：
    - bin_name: 素材箱名称
    - clip_name: 剪辑名称
    - track_idx: 轨道编号（1-10）
    - mmss_time: 插入时间（MM:SS格式）
    """
    # 参数验证
    original_track_idx = track_idx
    track_idx -= 1  # 转换为从0开始的索引

    if track_idx < 0 or track_idx > 9:
        raise ValueError("轨道编号必须为1-10之间的整数")

    # 计算插入时间
    try:
        insert_time = time_to_seconds(mmss_time) + TRACK_CONFIG["delays"][track_idx]
    except KeyError:
        raise ValueError(f"轨道 {original_track_idx} 没有配置延迟时间")

    # 获取剪辑对象
    if not (clip := project_cache.get_clip(bin_name, clip_name)):
        raise ValueError(f"素材不存在: {bin_name}/{clip_name}")


    # 获取目标轨道
    try:
        track = pymiere.objects.app.project.activeSequence.videoTracks[track_idx]
    except IndexError:
        raise ValueError(f"轨道 {original_track_idx} 不存在")

    # 执行插入操作
    try:
        track.overwriteClip(clip, time_from_seconds(insert_time))
        inserted_clip = track.clips[-1]  # 获取最新插入的剪辑
    except Exception as e:
        raise RuntimeError(f"插入失败: {str(e)}")

    # 更新轨道信息缓存
    project_cache.track_info[track_idx]["clip_count"] += 1
    project_cache.track_info[track_idx]["clips"].append(inserted_clip)

    # 设置位置
    if pos := TRACK_CONFIG["positions"].get(track_idx):
        if prop := project_cache.get_position_property(inserted_clip):
            try:
                normalized = [pos[0] / 1920, pos[1] / 1080]
                prop.setValue(normalized, True)
            except Exception as e:
                raise RuntimeError(f"位置设置失败: {str(e)}")
        else:
            print("警告：找不到位置属性，可能影响画面布局")

    print(f"成功插入 {clip_name} 到轨道 {original_track_idx}（时间：{mmss_time}）")
    return True


# ==================== 初始化 ====================
if __name__ == "__main__":
    # 初始化项目缓存
    project_cache = ProjectCache()
    try:
        project_cache.build_cache()
        print("项目缓存构建成功，检测到：")
        print(f"- 素材箱数量: {len(project_cache.bins)}")
        print(f"- 已缓存轨道数量: {len(project_cache.track_info)}")
    except Exception as e:
        raise RuntimeError(f"初始化失败: {str(e)}")

# ==================== 使用示例 ====================
# insert_and_position_clip("游戏素材", "暴雪Logo", 1, "00:05")
# insert_and_position_clip("界面元素", "死亡图标", 3, "01:30")

